﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace TestEngine
{
    public class TestSession
    {
        private readonly Question[] _questions;
        private Dictionary<Question, IQuestionState> _state;
        private int[] _order;
        private int _currentQuestion;
        private const double Eps = 10E-10;

        public TestSession(Question[] questions)
        {
            _questions = questions;
            TestCost = _questions.Sum(q => q.Cost);
            _currentQuestion = -1;
            Init();
        }

        public double TestCost { get; private set; }

        public int CurrentQuestionNumber { get { return _currentQuestion; } }

        public double GetTotalScore()
        {
            return _state.Sum(_ => _.Value != null ? _.Value.Score() : 0);
        }

        public double GetPercentageResult()
        {
            if (Math.Abs(TestCost - 0) < Eps) return 0;
            return GetTotalScore()/TestCost;
        }

        public Dictionary<Question, IQuestionState> GetResult()
        {
            return _state;
        }

        public Question NextQuestion()
        {
            if (_currentQuestion == _questions.Length - 1)
                return null;
            var index = _order[++_currentQuestion];
            return _questions[index];
        }

        public Question GetQuestion(int index)
        {
            var realIndex = _order[index];
            return _questions[realIndex];
        }

        public Question GetQuestion()
        {
            var realIndex = _order[_currentQuestion];
            return _questions[realIndex];
        }

        public Question GetQuestionById(int id)
        {
            return _questions.First(q => q.QuestionID == id);
        }

        public void Answer(Question question, string answer)
        {
            var questionState = new ClosedQuestionState(question as ClosedQuestion, answer);
            _state[question] = questionState;
        }

        public void Answer(Question question, params int[] variants)
        {
            var questionState = new OpenQuestionState(question as OpenQuestion, variants);
            _state[question] = questionState;
        }

        private void Init()
        {
            _order = Enumerable.Range(0, _questions.Length).OrderBy(e => Guid.NewGuid()).ToArray();
            _state = new Dictionary<Question, IQuestionState>();
            foreach (var question in _questions)
                _state.Add(question, null);
        }

        public int QuestionsCount { get { return _questions.Length; } }
    }
}
